In [1]:
%matplotlib inline
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
import numpy as np
import pandas as pd
import datetime as dt
from matplotlib import pyplot as plt
import uqer
from PyFin.api import *
from uqer import DataAPI as api
from QuantLib import *
plt.style.use('fivethirtyeight')
uqer.Client(token='f1b9bea1d0b4e489c5ab9b69c3e2326a1bee6057af858067dbd1546453f428b2')
Out[1]:
In [3]:
start_date = '2017-04-01'
end_date = '2017-08-01'
dates = makeSchedule(start_date, end_date, '4m', 'china.sse', )
mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
contract = 'ru1709'
In [4]:
def get_contracts(contract, start_date, end_date):
data = api.MktFutdGet(ticker=contract, beginDate=start_date, endDate=end_date, field='tradeDate,closePrice')
data['tradeDate'] = pd.to_datetime(data.tradeDate)
data.set_index('tradeDate', inplace=True)
data['closePrice'] = data['closePrice'].astype(float)
data['ret'] = data.closePrice.diff() / data.closePrice.shift(1)
data['vol'] = data['ret'].rolling(window=22).std() * np.sqrt(249)
return data
In [5]:
def get_contracts_bar(constract, start_date, end_date, unit=60):
start_date = dt.datetime.strptime(start_date, '%Y-%m-%d')
end_date = dt.datetime.strptime(end_date, '%Y-%m-%d')
datas = []
while start_date < end_date:
this_end_date = advanceDateByCalendar('china.sse', start_date, '10b')
df = api.MktFutureBarHistDateRangeGet(instrumentID=contract,
startDate=start_date.strftime('%Y%m%d'),
endDate=this_end_date.strftime('%Y%m%d'),
unit=unit,
field='dataDate,barTime,closePrice')
datas.append(df)
start_date = this_end_date
data = pd.concat(datas)
data = data[(data.barTime >= '09:00') & (data.barTime <= '16:00')]
data['tradeDate'] = pd.to_datetime(data.dataDate + 'T' + data.barTime)
data['closePrice'] = data['closePrice'].astype(float)
data['ret'] = data.closePrice.diff() / data.closePrice.shift(1)
data['vol'] = data['ret'].rolling(window=int(22 * 4 * 60 / unit)).std() * np.sqrt(249) * np.sqrt(4 * 60 / unit)
data.set_index('tradeDate', inplace=True)
return data[['closePrice', 'ret', 'vol']]
In [6]:
mkt_data = get_contracts_bar(contract, mkt_start_date, end_date)
In [7]:
strangle_width = 400.
lower_protect_area = 1000.
upper_protect_area = 800.
volatility = 0.42
risk_free_rate = 0.
dividend_rate = 0.
In [10]:
dates
Out[10]:
In [128]:
def cal_naive_delta(spot, pp1, pp2, cp1, cp2):
if spot <= pp2.strike():
return 0.
elif spot <= pp1.strike():
return -1.
elif spot <= cp1.strike():
return 0.
elif spot <= cp2.strike():
return 1.
else:
return 0.
def composite_payoff(spot, pp1, pp2, cp1, cp2):
return pp1(spot) - pp2(spot) + cp1(spot) - cp2(spot)
def hedging_contract(start_date, maturity_date, mkt_data, premium=None, naive_hedge=False, american_exercise=False):
spot_price = mkt_data[mkt_data.index < start_date.ISO()]['closePrice']
if hasattr(spot_price, '__iter__'):
spot_price = spot_price[-1]
lower_strike = spot_price
lower_bound = lower_strike - lower_protect_area
upper_strike = lower_strike + strangle_width
upper_bound = upper_strike + upper_protect_area
day_count = Actual365Fixed()
calendar = China(China.SSE)
calculation_date = start_date
Settings.instance().evaluationDate = calculation_date
spot_handle = RelinkableQuoteHandle(SimpleQuote(spot_price))
vol_handle = RelinkableQuoteHandle(SimpleQuote(volatility))
flat_ts = YieldTermStructureHandle(FlatForward(calculation_date, risk_free_rate, day_count))
dividend_yield = YieldTermStructureHandle(FlatForward(calculation_date, dividend_rate, day_count))
flat_vol_ts = BlackVolTermStructureHandle(BlackConstantVol(calculation_date, calendar, vol_handle, day_count))
bsm_process = BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts)
put_payoff1 = PlainVanillaPayoff(Option.Put, lower_strike)
put_payoff2 = PlainVanillaPayoff(Option.Put, lower_bound)
call_payoff1 = PlainVanillaPayoff(Option.Call, upper_strike)
call_payoff2 = PlainVanillaPayoff(Option.Call, upper_bound)
exercise = EuropeanExercise(maturity_date)
put_option1 = VanillaOption(put_payoff1, exercise)
put_option2 = VanillaOption(put_payoff2, exercise)
call_option1 = VanillaOption(call_payoff1, exercise)
call_option2 = VanillaOption(call_payoff2, exercise)
engine = AnalyticEuropeanEngine(bsm_process)
put_option1.setPricingEngine(engine)
put_option2.setPricingEngine(engine)
call_option1.setPricingEngine(engine)
call_option2.setPricingEngine(engine)
if not premium:
premium = put_option1.NPV() - put_option2.NPV() + call_option1.NPV() - call_option2.NPV()
price_series = mkt_data.loc[start_date.ISO(): maturity_date.ISO()]
previous_delta = 0.
previous_price = 0.
trading_pnl = 0.
trading_cost = 0.
for p in price_series.iterrows():
date = Date.from_date(p[0])
price = p[1]['closePrice']
vol = p[1]['vol']
if date != maturity_date:
Settings.instance().evaluationDate = date
spot_handle.linkTo(SimpleQuote(price))
vol_handle.linkTo(SimpleQuote(vol))
bsm_delta = put_option1.delta() - put_option2.delta() + call_option1.delta() - call_option2.delta()
if naive_hedge:
delta = cal_naive_delta(price, put_payoff1, put_payoff2, call_payoff1, call_payoff2)
else:
delta = bsm_delta
trading_pnl += (price - previous_price) * previous_delta
trading_cost += np.abs(delta - previous_delta) * 0.5 * (price + previous_price) * 0.0015
if american_exercise:
payoff = composite_payoff(price,
put_payoff1,
put_payoff2,
call_payoff1,
call_payoff2)
if price >= call_payoff2.strike() - 25.0 and payoff >= upper_protect_area - 25.:
break
elif price <= put_payoff2.strike() + 25.0 and payoff >= upper_protect_area - 25.:
break
previous_price = price
previous_delta = delta
final_price = mkt_data.loc[date.ISO()]['closePrice']
if hasattr(final_price, '__iter__'):
final_price = final_price[-1]
final_payoff = composite_payoff(final_price,
put_payoff1,
put_payoff2,
call_payoff1,
call_payoff2)
pnl_final = -final_payoff + premium + trading_pnl - trading_cost
return spot_price, final_price, vol, final_payoff, premium, trading_pnl, pnl_final, trading_cost
In [129]:
maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[1], '-1b'))
start_date = Date.from_date(dates[0])
hedging_contract(start_date, maturity_date, mkt_data, 646.)
Out[129]:
In [130]:
strangle_width = 400.
lower_protect_area = 1000.
upper_protect_area = 800.
volatility = 0.42
risk_free_rate = 0.
dividend_rate = 0.
premium = 769.
In [228]:
contract_definition = {
'ru0509': {
'start_date': '2005-04-01',
'end_date': '2005-08-01'
},
'ru0609': {
'start_date': '2006-04-01',
'end_date': '2006-08-01'
},
'ru0709': {
'start_date': '2007-04-01',
'end_date': '2007-08-01'
},
'ru0809': {
'start_date': '2008-04-01',
'end_date': '2008-08-01'
},
'ru0909': {
'start_date': '2009-04-01',
'end_date': '2009-08-01'
},
'ru1009': {
'start_date': '2010-04-01',
'end_date': '2010-08-01'
},
'ru1109': {
'start_date': '2011-04-01',
'end_date': '2011-08-01'
},
'ru1209': {
'start_date': '2012-04-01',
'end_date': '2012-08-01'
},
'ru1309': {
'start_date': '2013-04-01',
'end_date': '2013-08-01'
},
'ru1409': {
'start_date': '2014-04-01',
'end_date': '2014-08-01'
},
'ru1509': {
'start_date': '2015-04-01',
'end_date': '2015-08-01'
},
'ru1609': {
'start_date': '2016-04-01',
'end_date': '2016-08-01'
},
'ru1709': {
'start_date': '2017-04-01',
'end_date': '2017-08-01'
},
}
In [268]:
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df = pd.DataFrame(columns=cols)
for contract in contract_definition:
start_date = contract_definition[contract]['start_date']
end_date = contract_definition[contract]['end_date']
dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
mkt_data = get_contracts(contract, mkt_start_date, end_date)
for i, s_date in enumerate(dates[:-1]):
maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
start_date = Date.from_date(s_date)
hedge = hedging_contract(start_date, maturity_date, mkt_data, premium)
delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True)
py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
df = df.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
In [269]:
df['不对冲损益'] = -df['赔付'] + df['期权费']
In [270]:
df
Out[270]:
In [271]:
print("欧式行权: 2005 - 2017")
df.groupby(df['到期日'].dt.year).mean()
Out[271]:
In [233]:
df.std()
Out[233]:
In [234]:
df.mean()
Out[234]:
In [272]:
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df2 = pd.DataFrame(columns=cols)
for contract in list(contract_definition.keys())[5:]:
start_date = contract_definition[contract]['start_date']
end_date = contract_definition[contract]['end_date']
dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
mkt_data = get_contracts_bar(contract, mkt_start_date, end_date, unit=60)
for i, s_date in enumerate(dates[:-1]):
maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
start_date = Date.from_date(s_date)
hedge = hedging_contract(start_date, maturity_date, mkt_data, premium)
delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True)
py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
df2 = df2.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
In [273]:
df2['不对冲损益'] = -df2['赔付'] + df2['期权费']
In [274]:
df2
Out[274]:
In [275]:
df2.groupby(df2['到期日'].dt.year).mean()
Out[275]:
In [276]:
df2.std()
Out[276]:
In [277]:
df2.mean()
Out[277]:
In [278]:
df = df[df['合约'].isin(df2['合约'])].reset_index(drop=True)
In [279]:
s = df['不对冲损益'] - df2['不对冲损益']
In [280]:
df['diff'] = s
In [281]:
df[df['diff'] != 0]
Out[281]:
In [282]:
df2[df['diff'] != 0]
Out[282]:
In [283]:
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df = pd.DataFrame(columns=cols)
for contract in contract_definition:
start_date = contract_definition[contract]['start_date']
end_date = contract_definition[contract]['end_date']
dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
mkt_data = get_contracts(contract, mkt_start_date, end_date)
for i, s_date in enumerate(dates[:-1]):
maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
start_date = Date.from_date(s_date)
hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, american_exercise=True)
delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True, american_exercise=True)
py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
df = df.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
In [284]:
df['不对冲损益'] = -df['赔付'] + df['期权费']
In [285]:
df
Out[285]:
In [286]:
print("近似美式行权: 2013 - 2017")
df.groupby(df['到期日'].dt.year).mean()
Out[286]:
In [287]:
df.std()
Out[287]:
In [288]:
df.mean()
Out[288]:
In [ ]:
In [ ]: